<!--动态表单-->
<template>
    <div>
        <el-dialog
            :before-close="close"
            append-to-body
            :visible.sync="visible">
            <template>
                <div slot="title" style="position: relative">
                    <span class="el-dialog__title">{{ type.toUpperCase() }} // {{ form.id }}  // {{ name }}</span>
                    <el-button type="primary" style="position: absolute;right:50px;top: 6px" plain class="el-icon-check"
                               @click="save"/>
                </div>
            </template>
            <el-tabs :value="'1'">
                <el-tab-pane label="类型属性" name="first">
                    <el-form label-position="top" :model="form">
                        <div v-for="(v,k) in JsonSchema.SCHEMA_KEYS[type.toUpperCase()].properties" :key="k">
                            <el-form-item v-if="JsonSchema.SCHEMA_KEYS[type.toUpperCase()].required.includes(k)"
                                          :label="`${k} :  ${v.description}`">
                                <el-switch v-if="v.type==='boolean'" v-model="form[k]"/>
                                <el-input-number v-else-if="['number', 'integer'].includes(v.type)"
                                                 v-model="form[k]" controls-position="right"/>
                                <el-input v-else v-model="form[k]" type="textarea" :autosize="{maxRows: 1}"/>
                            </el-form-item>
                        </div>
                    </el-form>
                    <el-divider/>
                    <el-form :inline="true">
                        <div v-for="([k,v],i) in other.value" :key="k">
                            <el-form-item>
                                <i class="el-icon-delete" @click="delProps(i)"/>
                            </el-form-item>
                            <el-form-item label="属性名 " :rules="other.rules.key">
                                <el-input v-model="other.value[i][0]" size="mini"/>
                            </el-form-item>
                            <el-form-item label="值类型">
                                <el-select v-model="other.value[i][2]" size="mini" @change="typeProps($event,i)">
                                    <el-option
                                        v-for="item in ['string', 'number', 'boolean', 'object', 'array', 'null', 'integer']"
                                        :key="item"
                                        :label="item"
                                        :value="item">
                                    </el-option>
                                </el-select>
                            </el-form-item>
                            <el-form-item v-if="['object', 'array', 'null'].includes(other.value[i][2])" label="属性值"
                                          :rules="other.rules.value">
                                <el-input v-model="other.value[i][1]" @input="v = $event;"
                                          size="mini" type="textarea" :autosize="{maxRows: 1}"/>
                            </el-form-item>
                            <el-form-item v-else label="属性值">
                                <el-switch v-if="other.value[i][2]==='boolean'" v-model="other.value[i][1]"/>
                                <el-input-number v-else-if="['number', 'integer'].includes(other.value[i][2])"
                                                 v-model="other.value[i][1]" controls-position="right" size="mini"/>
                                <el-input v-else v-model="other.value[i][1]" size="mini" type="textarea"
                                          :autosize="{maxRows: 1}"/>
                            </el-form-item>
                        </div>
                    </el-form>
                    <el-button type="primary" @click="addProps">新增属性</el-button>
                </el-tab-pane>
                <el-tab-pane label="通用属性" name="second">
                    <el-form :inline="true" :model="form">
                        <el-form-item label="name " :rules="other.rules.name">
                            <el-input v-model="name" size="mini" :disabled="!origin.parent || origin.parent.type === 'array'"/>
                        </el-form-item>
                        <el-form-item label="type ">
                            <el-select v-model="form.type" size="mini" disabled>
                                <el-option
                                    v-for="item in ['string', 'number', 'boolean', 'object', 'array', 'null', 'integer']"
                                    :key="item"
                                    :label="item"
                                    :value="item">
                                </el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="require">
                            <el-switch size="mini"
                                       v-model="form.require"
                                       active-color="#13ce66"
                                       inactive-color="#ff4949">
                            </el-switch>
                        </el-form-item>
                    </el-form>
                    <el-form label-position="top" :model="form">
                        <el-form-item label="title :  字段标题">
                            <el-input v-model="form.title" type="textarea" :autosize="{maxRows: 1}"/>
                        </el-form-item>
                        <el-form-item label="description :  字段相关说明">
                            <el-input v-model="form.description" type="textarea" :autosize="{maxRows: 1}"/>
                        </el-form-item>
                        <el-form-item label="default :  默认值">
                            <el-input v-model="form.default" type="textarea" :autosize="{maxRows: 1}"/>
                        </el-form-item>
                        <el-form-item label="enum :  枚举值列表"
                                      v-if="['string','number','integer'].includes(form.type)">
                            <el-tag
                                :key="tag"
                                v-for="tag in form.enum"
                                closable
                                :disable-transitions="false"
                                @close="form.enum.splice(form.enum.indexOf(tag), 1)">
                                {{ tag }}
                            </el-tag>
                            <el-input
                                class="input-new-tag"
                                v-if="control.visible"
                                v-model="control.value"
                                ref="saveTagInput"
                                @keyup.enter.native="control.handleInputConfirm"
                                @blur="control.handleInputConfirm">
                                >
                            </el-input>
                            <el-button v-else class="button-new-tag" size="small" @click="control.showInput()">+ Add
                            </el-button>
                        </el-form-item>
                    </el-form>
                </el-tab-pane>
                <el-tab-pane label="高级设置" name="third">
                    <el-form label-position="top" label-width="80px">
                        <el-form-item label="整体替换 (修改将重新修改所有属性，请注意检查)">
                            <el-input v-model="allJson" type="textarea"/>
                        </el-form-item>
                        <el-form-item label="附加设置 (修改将重载类型自定义项，请注意检查)">
                            <el-input v-model="JsonSchema.getView(type.toUpperCase()).view"
                                      type="textarea"/>
                        </el-form-item>
                    </el-form>
                </el-tab-pane>
            </el-tabs>
        </el-dialog>
    </div>
</template>


<script>
import {JsonSchema,infoNotify} from "@/view/JsonSchema";

export default {
    computed: {
        JsonSchema() {
            return JsonSchema
        },
        allJson: {
            get() {
                return JSON.stringify(this.form);
            },
            set(val) {
                let obj = {}
                try {
                    obj = JSON.parse(val);
                } catch (e) {
                    return infoNotify('请输入正确的json格式');
                }
                this.form = obj;
                this.otherProps();
            }
        },
    },
    data() {
        return {
            visible: false,
            type: 'string',
            name: '未知属性',
            control: {
                visible: false,
                value: '',
                handleClose: (tag) => {
                    this.form.enum.splice(this.form.enum.indexOf(tag), 1);
                },
                showInput: () => {
                    this.control.visible = true;
                    this.$nextTick(() => {
                        this.$refs.saveTagInput.$refs.input.focus();
                    });
                },
                handleInputConfirm: () => {
                    let value = this.control.value;
                    if (value) {
                        this.form.enum ??= [];
                        this.form.enum.push(value);
                    }
                    this.control.visible = false;
                    this.control.value = '';
                }
            },
            form: {
                type: 'string',
                title: '标题',
                description: '描述',
                default: '默认值',
                enum: ['上海', '北京', '广州', '深圳']
            },
            origin: {
                name: '属性名',
                title: '标题',
                type: 'string',
                require: true,
                description: '描述',
                default: '默认值',
                enum: ['上海', '北京', '广州', '深圳']
            },
            other: {
                json: '{}',
                value: [],
                keys: [],
                rules: {
                    key: [{required: true, message: '请输入属性名', trigger: 'blur'},
                        {
                            trigger: 'blur',
                            validator: (rule, value, callback) => this.other.keys.includes(value) ? callback(new Error('属性名已存在')) : callback()
                        }],
                    value: [{required: true, message: '请输入属性名', trigger: 'blur'},
                        {
                            trigger: 'blur',
                            validator: (rule, value, callback) => {
                                try {
                                    JSON.parse(value);
                                    callback();
                                } catch (err) {
                                    callback(new Error('请输入正确的json格式'))
                                }
                            },
                        }
                    ],
                    name: [{required: true, message: '请输入属性名', trigger: 'blur'},
                        {
                            trigger: 'blur', validator: (rule, value, callback) =>
                                Object.keys(this.origin.parent.properties).includes(value) ? callback(new Error('属性名已存在')) : callback()
                        }
                    ],
                }
            },
        };
    },
    mounted() {
        // JsonSchema.SCHEMA_KEYS.ANY.properties
    },
    methods: {
        open(row) {
            this.type = row.type;
            Object.assign(this.form, row);
            this.form.require = row.require;
            this.origin = row;
            this.name = this.origin.name;
            this.visible = true;
            this.otherProps();
        },
        close() {
            this.visible = false;
            this.name = '未知属性';
            this.other.value = []
            this.form = {}
        },
        save() {
            Object.assign(this.form, Object.fromEntries(JsonSchema.convertEntries(this.other.value)));
            Object.assign(this.origin, this.form);
            (this.name !== this.origin.name) && (this.origin.name = this.name);
            this.$emit('updateTable');
            this.close();
        },
        //重新设计展示类型：0.禁止展示关键字，1.已有关键字；2.额外关键字； ALL-通用-禁止
        otherProps() {
            let anyKeys = Object.keys(JsonSchema.SCHEMA_KEYS.ANY.properties);
            let typeKeys = Object.keys(JsonSchema.SCHEMA_KEYS[this.type.toUpperCase()].properties);
            let keys = [...anyKeys, ...typeKeys];
            this.other.keys = keys;
            let other = {}
            Object.entries(this.form).forEach(([k, v]) => { //排除已经展示属性
                if (!keys.includes(k)) {
                    other[k] = v;
                }
            });
            this.other.json = JSON.stringify(other, null, 4);
            this.other.value = JsonSchema.toEntries(other);
        },
        addProps() {
            this.other.value.push([JsonSchema.genId(), '', 'string']);
        },
        delProps(i) {
            this.other.value.splice(i, 1);
        },
        typeProps(type, i) {
            this.other.value[i][1] = JsonSchema.convertView(JsonSchema.convertView(this.other.value[i][1]), type);
        },
    }
}
</script>